﻿#pragma once
#include <QHash>
#include <QList>
#include <QObject>
#include <QString>
// #include "../Network/NetClient.h"
#include <QMutex>
#include "Data.h"
#include "friend.qpb.h"
#include "message_storage.qpb.h"
#include "user.qpb.h"

// 前置声明解决循环包含
class NetClient;

namespace model
{
////////////////////////////////////////////
/// 用来管理客户端传输的所有数据的一个单例类
////////////////////////////////////////////
class DataCenter : public QObject
{
    Q_OBJECT
public:
    /* 工具方法 */
    static DataCenter* get_instance();
    void               init_data_file();
    void               write_data_file();
    void               read_data_file();
    int                top_this_session(ChatSession* this_session);
    void               push_back_message_list(const QString& chat_session_id, const Message& message);
    void               add_unread_cnt(const QString& chat_session_id);
    int                get_unread_cnt(const QString& chat_session_id);
    void               clear_unread_cnt(const QString& chat_session_id);
    bool               is_friend(const QString& user_id);
    void               push_front_apply_list(const UserInfo& user_info);
    UserInfo           remove_from_apply_list(const QString& user_id);
    void               push_front_friend_list(const UserInfo& user_info);
    void               del_sepc_friend(const QString& user_id);
public:
    /* 网络相关的异步函数 */
    void ping();
    void init_socket();
    void get_myself_info_async();
    void get_friend_list_async();
    void get_chat_session_list_async();
    void get_friend_apply_list_async();
    void get_recent_messages_async(const QString& chat_session_id, int cnt, bool update_ui);
    void send_text_message_async(const QString& chat_session_id, const QString& content);
    void send_image_message_async(const QString& chat_session_id, const QByteArray& image);
    void send_file_message_async(const QString& chat_session_id, const QByteArray& file_data, const QString& file_name);
    void send_speech_message_async(const QString& chat_session_id, const QByteArray& audio_data);
    void receive_message(const QString& chat_session_id);
    void set_user_nick_name_async(const QString& nick_name);
    void set_user_description_async(const QString& desc);
    void set_user_phone_num_async(const QString& phone_num, const QString& phone_verify_code_id, const QString& phone_verify_code);
    void get_phone_verify_code_async(const QString& phone_num);
    void set_user_avatar_async(const QByteArray& image);
    void del_friend_async(const QString& user_id);
    void add_friend_async(const QString& user_id);
    void accept_friend_apply_async(const QString& user_id);
    void reject_friend_apply_async(const QString& user_id);
    void create_group_async(const QList<QString>& user_ids);
    void get_group_member_list_async(const QString& chat_session_id);
    void search_user_async(const QString& search_key);
    void search_history_message_async(const QString& chat_session_id, const QString& search_key);
    void search_history_message_by_time_async(const QString& chat_session_id, qint64 start_time, qint64 end_time);
    void user_login_async(const QString& user_name, const QString& pwd);
    void user_register_async(const QString& user_name, const QString& pwd);
    void phone_login_async(const QString& phone_num, const QString& verify_code);
    void phone_register_async(const QString& phone_num, const QString& verify_code);
    void get_single_file_async(const QString& file_id);
    void speech_recognition_async(const QByteArray& data);
public:
    /* get 和 set 方法 以及网络相关的回调方法 */
    QString             get_login_session_id() const;
    UserInfo*           get_cur_user_info() const;
    QList<UserInfo>*    get_friend_list() const;
    QList<ChatSession>* get_chat_session_list() const;
    QList<UserInfo>*    get_friend_apply_list() const;
    QList<Message>*     get_message_list(const QString& chat_session_id) const;
    ChatSession*        get_chat_session(const QString& chat_session_id) const;
    ChatSession*        get_chat_session_by_user_id(const QString& user_id) const;
    UserInfo*           get_user_info_by_user_id(const QString& user_id) const;
    const QString       get_cur_session_id() const;
    const QString&      get_phone_verify_code_id() const;
    void                set_cur_session_id(const QString& chat_session_id);
    void                set_cur_user_info(std::shared_ptr<chat::GetUserInfoRsp> user_info_resp);
    void                set_friend_list(std::shared_ptr<chat::GetFriendListRsp> friend_list_resp);
    void                set_chat_session_list(std::shared_ptr<chat::GetChatSessionListRsp> chat_session_list_resp);
    void                set_friend_apply_list(std::shared_ptr<chat::GetPendingFriendEventListRsp> friend_apply_list_resp);
    void                set_recent_messages(const QString& chat_session_id, std::shared_ptr<chat::GetRecentMsgRsp> recent_messages);
    void                set_cur_user_info_nick_name(const QString& nick_name);
    void                set_cur_user_info_desc(const QString& desc);
    void                set_cur_user_info_phone_num(const QString& phone_num);
    void                set_phone_verify_code_id(std::shared_ptr<chat::PhoneVerifyCodeRsp> verify_code_resp);
    void                set_cur_user_info_avatar(const QByteArray& image);
    void                add_group_member_list(const QString& chat_session_id, std::shared_ptr<chat::GetChatSessionMemberRsp> sepc_member_list_rsp);
    QList<UserInfo>     get_group_member_list(const QString& chat_session_id);
    void                set_search_user_result(std::shared_ptr<chat::FriendSearchRsp> search_rsp);
    QList<UserInfo>*    get_search_user_result();
    void                set_search_history_msg(const QList<chat::MessageInfo>& pb_message);
    QList<Message>*     get_search_message_result();
    void                set_login_session_id(const QString& login_session_id);
signals:
    /* HTTP 通信中发送的信号 */
    void get_myself_info_done();                                                                     // 获取用户信息完成信号
    void get_friend_list_done();                                                                     // 获取好友列表完成信号
    void get_chat_session_list_done();                                                               // 获取会话列表完成信号
    void get_friend_apply_list_done();                                                               // 获取好友申请列表完成信号
    void get_recent_messages_done(const QString& chat_session_id);                                   // 获取最近消息完成信号
    void get_recent_messages_done_no_update_ui(
        const QString& chat_session_id);                                                             // 获取最近消息完成信号(不需要更新UI)
    void send_message_done(MessageType type, const QByteArray& content, const QString& extra_info);  // 发送消息完成信号
    void update_last_message(const QString& chat_session_id);                                        // 给SessionItem发信号, 用于更新最后一条消息
    void receive_message_done(const Message& message);                                               // receive_message()这个函数处理完消息后，会发送这个信号，用于更新MessageShowArea内容
    void get_phone_verify_code_done();                                                               // 获取手机验证码完成信号, 在登录时会用到
    void set_cur_user_info_avatar_done();                                                            // 设置用户头像完成信号
    void del_friend_done();                                                                          // 删除好友完成信号
    void del_cur_session();                                                                          // 删除当前选中的会话信号, 在MainWidget中处理
    void add_friend_done();                                                                          // 添加好友完成信号
    void accept_friend_apply_done(const QString& nick_name);                                         // 接受好友申请完成信号
    void reject_friend_apply_done(const QString& nick_name);                                         // 拒绝好友申请完成信号
    void creat_group_done();                                                                         // 创建群聊申请完成信号
    void get_group_member_list_done();                                                               // 获取群聊群员列表结束
    void search_user_done();                                                                         // 查找用户搜索结束
    void search_history_message_done();                                                              // 搜索历史消息结束
    void user_login_done(bool ok, const QString& reason);                                            // 用户名登录结束
    void user_register_done(bool ok, const QString& reason);                                         // 用户名注册结束
    void phone_login_done(bool ok, const QString& resaon);                                           // 手机号登录结束
    void phone_register_done(bool ok, const QString& reason);                                        // 手机号注册结束
    void get_single_file_done(const QString& file_id, const QByteArray& file_content);               // 获取单个文件完成信号
    void speech_recognition_done(bool ok, const QString& reason, const QString& text);               // 语音识别完成信号
    /* WebSocket 通信中发送的信号 */
    void receive_friend_apply();                                 // 收到好友申请信号
    void receive_accept_friend_apply(const QString& nick_name);  // 收到同意好友申请的信号
    void receive_reject_friend_apply(const QString& nick_name);  // 收到拒绝好友申请的信号
    void receive_create_group();                                 // 收到创建群聊信号
private:
    static DataCenter* instance;                                 // 单例模式
    DataCenter();
    DataCenter(const DataCenter&)            = delete;
    DataCenter& operator=(const DataCenter&) = delete;
    /// @brief 登录会话ID
    /// 这个信息是登录成功后从服务器返回的，客户端需要长久保存这个信息
    /// 后序每次启动，都从文件中读取这个信息，这样就可以实现自动登录
    /// 当用户显式的点击登出时，需要清除这个信息
    QString login_session_id = "";
    QString cur_session_id   = "";  // 当前选中的会话ID
    /// @brief  TODO, 这里都改成指针, 要不然太慢
    QList<ChatSession>*              chat_session_list     = nullptr;  // 当前用户的聊天会话列表
    UserInfo*                        cur_user_info         = nullptr;  // 当前用户信息
    QList<UserInfo>*                 friend_list           = nullptr;  // 当前用户的好友列表
    QList<UserInfo>*                 apply_list            = nullptr;  // 好友申请列表
    QHash<QString, QList<UserInfo>>* member_list           = nullptr;  // 群成员列表，key为群(会话)id，value为群成员列表
    QHash<QString, QList<Message>>*  message_list          = nullptr;  // 消息列表，key为会话id，value为消息列表
    QHash<QString, int>*             unread_count          = nullptr;  // 未读消息计数，key为会话id，value为未读消息数量
    QList<UserInfo>*                 search_user_result    = nullptr;  // 搜索用户结果
    QList<Message>*                  search_message_result = nullptr;  // 搜索消息结果
    QString                          data_file_path        = "";       // 数据文件路径
    QString                          phone_verify_code_id  = "";       // 手机验证码ID
    NetClient*                       net_client            = nullptr;  // 网络客户端
    QMutex                           session_list_mutex;               // 互斥锁
};
}  // end namespace model
